﻿#pragma once
#ifndef Component_hpp
#define Component_hpp

#include<vector>
#include<map>
#include<functional>
#include<memory>
#include"./DataTypeDef.hpp"
#include"./Device.hpp"
#include"../Concurrency/SpinLock.hpp"


namespace MMF
{

    class MMFComponentBase;

    //函数类型
    using MMFDataFunc = std::function<void(const MMFDataBuffer& buffers)>;

    //端口类型
    struct MMFPort
    {
        MMFDataFunc mHandler;                       ///< 端口使用的函数
        MMFComponentBase* mOwner;                   ///< 端口所属组件
        MMFComponentBase* mParent;                  ///< 父组件
        uint32_t mIndexOfParent;                    ///< 在父组件中端口序号
        uint32_t mIndex;                            ///< 自己的序号
    };

    enum class MMFComponentErr
    {
        OK = 0,
        OUT_PORT_ERR = -1,                       ///< 输出端口ID错误
        PORT_IS_CONNECTED = -2,                  ///< 该端口已经链接了
        PORT_IS_DUSCONNECTED = -3,               ///< 该端口未链接
        PORT_DATA_TYPE_ERR = -4                  ///< 端口数据错误
    };

    /***
     * 组件信息诊断信息
    */
    struct MMFComponentInfo
    {
        std::atomic<bool> mRun;                  ///< 设备是否在运行         
        uint64_t mInBytes;                       ///< 向组件中输入数据字节数
        uint64_t mOutBytes;                      ///< 设备向外输出多少数据
        std::string mName;                       ///< 设备名字
    };

    /***
     * 基础组件的基类
     * 规定了一些接口
     * 提供统一的行为
    */
    class MMFComponentBase
    {

    protected:

        //上下文
        MMFCtx mCtx;

        //设备信息
        MMFDevice* mDevice;

        //状态信息
        MMFComponentInfo mInfo;
        
        //输入端口
        //此数据类型应该u在初始化的时候讲里面的数据类型创建
        std::vector<std::shared_ptr<MMFPort>> mInPorts;

        //输出端口
        std::map<uint32_t, std::vector<std::shared_ptr<MMFPort>>> mOutPorts;
        
    public:

        MMFComponentBase(const MMFCtx& ctx, MMFDevice* device, const std::string& name = "");
        virtual ~MMFComponentBase();

        //开始函数
        virtual void Start() = 0;

        //运行函数
        virtual void Run() = 0;

        //停止函数
        virtual void Abort() = 0;

        //暂停函数
        virtual void Pause() = 0;

        //回复函数
        virtual void Resume() = 0;

        //获取输入端口数
        virtual uint32_t InPortNum();

        //数去输出端口数量
        virtual uint32_t OutPortNum();

        //获取输入端口数据类型
        virtual MMFDataType GetInDataType(uint32_t portIndex);

        //获取输出端口数据类型
        virtual MMFDataType GetOutDataType(uint32_t portIndex);

        //获取输入端口
        std::shared_ptr<MMFPort> GetInPort(uint32_t portIndex);

        //设置参数
        virtual void Config(const MMFDeviceCfgBase& cfg) = 0;

        //获取参数
        virtual const MMFDeviceCfgBase& Config() = 0;

        //设置上下文
        virtual void Ctx(const MMFCtx& ctx) = 0;

        //获取上下文
        virtual MMFCtx Ctx() = 0;

        //添加链接
        MMFComponentErr AddConnection(uint32_t outPortIdx, std::shared_ptr<MMFPort>& port);

        //删除连接
        MMFComponentErr DeleteConnection(uint32_t outPortIdx, std::shared_ptr<MMFPort>& port);

        const MMFComponentInfo& Info();
    };
}

#endif